/*
 * author      : dormi330
 * date        : 2018/6/28
 * description : 订单controller
 */

package com.deep.trade.adaptor.provided.rest;

import com.deep.trade.application.AppRuntimeEvn;
import com.deep.trade.application.OrderFacadeImpl;
import com.deep.trade.application.exception.LayerControllerException;
import com.deep.trade.common.CommonUtils;
import com.deep.trade.common.HttpResponsePayload;
import com.deep.trade.order.dto.*;
import com.github.pagehelper.PageInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import static org.springframework.util.MimeTypeUtils.APPLICATION_JSON_VALUE;


@Controller
@RequestMapping(value = "/api/v1/order")
public class OrderController {

    private Logger logger = LoggerFactory.getLogger(this.getClass().getName());

    private AppRuntimeEvn appRuntimeEvn;
    private OrderFacadeImpl orderFacadeImpl;

    private HttpResponseAssembler assembleService;

    @Autowired
    public OrderController(
            AppRuntimeEvn appRuntimeEvn
            , OrderFacadeImpl orderFacadeImpl
            , HttpResponseAssembler assembleService
    ) {
        this.appRuntimeEvn = appRuntimeEvn;
        this.orderFacadeImpl = orderFacadeImpl;
        this.assembleService = assembleService;
    }

    // ============ 查询 ===========

    /**
     * 订单列表, 不包含 sku
     */
    @ResponseBody
    @RequestMapping(value = "/list", method = RequestMethod.GET)
    public HttpResponsePayload tradeOrderListOfMember(
            @RequestParam(required = false) String token,
            @RequestParam(required = false) String tenantCode,
            @RequestParam(value = "page", required = false, defaultValue = "1") int page,
            @RequestParam(value = "size", required = false, defaultValue = "10") int size
    ) throws Exception {
        if (null == token) throw LayerControllerException.argumentNotFound("token");
        if (null == tenantCode) throw LayerControllerException.argumentNotFound("tenantCode");

        logger.info("{}, tenantCode={}, token={}", CommonUtils.currentClassAndMethod(), tenantCode, token);
        appRuntimeEvn
                .ensureTenantCode(tenantCode)
                .ensureToken(token);

        PageInfo<OutDtoTradeOrder> pageInfo = orderFacadeImpl.tradeOrderListOfMember(page, size);
        return assembleService.happy(pageInfo);
    }

    /**
     * 订单列表, 包含 sku
     */
    @ResponseBody
    @RequestMapping(value = "/list-with-sku", method = RequestMethod.GET)
    public HttpResponsePayload tradeOrderWithSkuListOfMember(
            @RequestParam(required = false) String token,
            @RequestParam(required = false) String tenantCode,
            @RequestParam(value = "page", required = false, defaultValue = "1") int page,
            @RequestParam(value = "size", required = false, defaultValue = "10") int size
    ) throws Exception {
        if (null == token) throw LayerControllerException.argumentNotFound("token");
        if (null == tenantCode) throw LayerControllerException.argumentNotFound("tenantCode");

        logger.info("{}, tenantCode={}, token={}", CommonUtils.currentClassAndMethod(), tenantCode, token);
        appRuntimeEvn
                .ensureTenantCode(tenantCode)
                .ensureToken(token);

        PageInfo<OutDtoTradeOrderWithSku> pageInfo = orderFacadeImpl.tradeOrderWithSkuListOfMember(page, size);
        return assembleService.happy(pageInfo);
    }

    /**
     * 订单详情
     */
    @ResponseBody
    @RequestMapping(value = "/detail", method = RequestMethod.GET)
    public HttpResponsePayload tradeOrderDetail(
            @RequestParam(required = false) String token,
            @RequestParam(required = false) String tenantCode,
            @RequestParam("id") String orderSummaryId
    ) throws Exception {
        if (null == token) throw LayerControllerException.argumentNotFound("token");
        if (null == tenantCode) throw LayerControllerException.argumentNotFound("tenantCode");

        logger.info("{}, tenantCode={}, orderSummaryId={}", CommonUtils.currentClassAndMethod(), tenantCode, orderSummaryId);
        appRuntimeEvn
                .ensureTenantCode(tenantCode)
                .ensureToken(token);

        OutDtoOrderDetail outDtoOrderDetail = orderFacadeImpl.tradeOrderDetail(orderSummaryId);
        return assembleService.happy(outDtoOrderDetail);
    }

    // ============ 查询 ===========

    /**
     * 创建订单
     */
    @ResponseBody
    @RequestMapping(value = {"", "/"}, method = RequestMethod.POST, consumes = APPLICATION_JSON_VALUE, produces = APPLICATION_JSON_VALUE)
    public HttpResponsePayload placeOrder(
            @RequestParam(required = false) String token,
            @RequestParam(required = false) String tenantCode,
            @RequestBody InDtoPlaceOrder inDtoPlaceOrder
    ) throws Exception {
        if (null == token) throw LayerControllerException.argumentNotFound("token");
        if (null == tenantCode) throw LayerControllerException.argumentNotFound("tenantCode");

        logger.info("{}, {}", CommonUtils.currentClassAndMethod(), inDtoPlaceOrder);
        appRuntimeEvn
                .ensureTenantCode(tenantCode)
                .ensureToken(token);

        String orderSummaryId = orderFacadeImpl.placeOrder(inDtoPlaceOrder);
        return assembleService.happy(orderSummaryId);
    }

    /**
     * 取消订单
     */
    @ResponseBody
    @RequestMapping(value = "/cancel", method = RequestMethod.POST)
    public HttpResponsePayload cancelTradeOrder(
            @RequestParam(required = false) String token,
            @RequestParam(required = false) String tenantCode,
            @RequestBody(required = false) InDtoCancelOrder inDtoCancelOrder
    ) throws Exception {
        if (null == token) throw LayerControllerException.argumentNotFound("token");
        if (null == tenantCode) throw LayerControllerException.argumentNotFound("tenantCode");

        logger.info("{}, tenantCode={}, inDtoCancelOrder={}", CommonUtils.currentClassAndMethod(), inDtoCancelOrder);
        appRuntimeEvn
                .ensureTenantCode(tenantCode)
                .ensureToken(token);

        orderFacadeImpl.cancelTradeOrder(inDtoCancelOrder);
        return assembleService.happy();
    }

    /**
     * 删除订单
     */
    @ResponseBody
    @RequestMapping(value = {"", "/"}, method = RequestMethod.DELETE)
    public HttpResponsePayload deleteTradeOrder(
            @RequestParam(required = false) String token,
            @RequestParam(required = false) String tenantCode,
            @RequestBody(required = false) InDtoCancelOrder inDtoCancelOrder
    ) throws Exception {
        logger.info("{}, tenantCode={}, inDtoCancelOrder={}", CommonUtils.currentClassAndMethod(), inDtoCancelOrder);
        appRuntimeEvn
                .ensureTenantCode(tenantCode)
                .ensureToken(token);

        orderFacadeImpl.deleteTradeOrder(inDtoCancelOrder);
        return assembleService.happy();
    }

    /**
     * 订单审核
     */
    @ResponseBody
    @RequestMapping(value = "/audit", method = RequestMethod.POST)
    public HttpResponsePayload auditTradeOrder(
            @RequestParam(required = false) String token,
            @RequestParam(required = false) String tenantCode,
            @RequestBody InDtoAuditOrder inDtoAuditOrder
    ) throws Exception {
        logger.info("{}, inDtoAuditOrder={}", CommonUtils.currentClassAndMethod(), inDtoAuditOrder);
        appRuntimeEvn
                .ensureTenantCode(tenantCode)
                .ensureToken(token);

        orderFacadeImpl.auditTradeOrder(inDtoAuditOrder);
        return assembleService.happy();
    }

    /**
     * 支付单个 tradeOrder
     */
    @ResponseBody
    @RequestMapping(value = "/trade-order/pay", method = RequestMethod.POST)
    public HttpResponsePayload payTradeOrder(
            @RequestParam(required = false) String token,
            @RequestParam(required = false) String tenantCode,
            @RequestBody InDtoPayTradeOrder inDtoPayTradeOrder
    ) throws Exception {
        logger.info("{}, inDtoPayTradeOrder={}", CommonUtils.currentClassAndMethod(), inDtoPayTradeOrder);
        appRuntimeEvn
                .ensureTenantCode(tenantCode)
                .ensureToken(token);

        orderFacadeImpl.payTradeOrder(inDtoPayTradeOrder);
        return assembleService.happy();
    }

    /**
     * 支付 OrderSummary
     */
    @ResponseBody
    @RequestMapping(value = "/order-summary/pay", method = RequestMethod.POST)
    public HttpResponsePayload payOrderSummary(
            @RequestParam(required = false) String token,
            @RequestParam(required = false) String tenantCode,
            @RequestBody InDtoPayOrderSummary inDtoPayOrderSummary
    ) throws Exception {
        logger.info("{}, inDtoPayTradeOrder={}", CommonUtils.currentClassAndMethod(), inDtoPayOrderSummary);
        appRuntimeEvn
                .ensureTenantCode(tenantCode)
                .ensureToken(token);

        orderFacadeImpl.payOrderSummary(inDtoPayOrderSummary);
        return assembleService.happy();
    }

    /**
     * 确认收货
     */
    @ResponseBody
    @RequestMapping(value = "/confirm-receipt", method = RequestMethod.POST)
    public HttpResponsePayload confirmReceipt(
            @RequestParam(required = false) String token,
            @RequestParam(required = false) String tenantCode,
            @RequestBody InDtoCancelOrder inDtoCancelOrder
    ) throws Exception {
        logger.info("{}, tradeOrderId={}", CommonUtils.currentClassAndMethod(), inDtoCancelOrder);
        appRuntimeEvn
                .ensureTenantCode(tenantCode)
                .ensureToken(token);

        orderFacadeImpl.orderConfirmationOfReceipt(inDtoCancelOrder.getTradeOrderId());
        return assembleService.happy();
    }

    /**
     * 计算 若干 sku+qty 所需要付的钱的额度
     */
    @ResponseBody
    @RequestMapping(value = "/calculate-payment", method = RequestMethod.POST)
    public HttpResponsePayload calculatePayment(
            @RequestParam(required = false) String token,
            @RequestParam(required = false) String tenantCode,
            @RequestBody InDtoPlaceOrder inDtoPlaceOrder
    ) throws Exception {
        logger.info("{}, inDtoPlaceOrder={}", CommonUtils.currentClassAndMethod(), inDtoPlaceOrder);
        appRuntimeEvn
                .ensureTenantCode(tenantCode)
                .ensureToken(token);

        OutDtoCalculatePayment outDtoCalculatePayment = orderFacadeImpl.calculatePayment(inDtoPlaceOrder);
        return assembleService.happy(outDtoCalculatePayment);
    }
}
